package com.litbw.gui;

import java.awt.LayoutManager;
import java.util.Observable;
import java.util.Observer;

import javax.swing.JPanel;

import com.litbw.publicobservable.PublicObservable;

/**
 * The ObservablePanel is a subclass of JPanel which has public methods to
 * control an Observable object. This allows for the Panel to also be it's
 * own Observable. It further implements Observer so that ObservablePanels
 * may send/recieve messages from one another.<BR><BR>
 * Subclassing AbstractMessage makes a convenient argument to use with
 * notifyObservers(Object).
 * @author Michael Morris
 *
 */
public class AbstractObservablePanel extends JPanel
						implements Observer {
	
	/**
	 * A generated serialVersionUID.
	 */
	private static final long serialVersionUID = -7614798718977793665L;
	
	/** The observable. **/
	private PublicObservable obs = new PublicObservable();
	
	/**
	 * Create an ObservablePanel.
	 */
	public AbstractObservablePanel() {
		super();
	}
	
	/**
	 * Create an ObservablePanel specifying whether it should be double
	 * buffered.
	 * @param isDoubleBuffered True if double buffered.
	 */
	public AbstractObservablePanel(final boolean isDoubleBuffered) {
		super(isDoubleBuffered);
	}
	
	/**
	 * Create an ObservablePanel specifying the LayoutManager to use.
	 * @param layout The LayoutManager to use.
	 */
	public AbstractObservablePanel(final LayoutManager layout) {
		super(layout);
	}
	
	/**
	 * Create an ObservablePanel specifying the LayoutManager to use, as well
	 * as if it should be double buffered.
	 * @param layout The LayoutManager to use.
	 * @param isDoubleBuffered True if double buffered.
	 */
	public AbstractObservablePanel(final LayoutManager layout,
			final boolean isDoubleBuffered) {
		super(layout, isDoubleBuffered);	
	}
	
	/**
	 * Signal that the Observable has changed.
	 */
	public void setChanged() {
		obs.setChanged();
	}
	
	/**
	 * Clear the changed state of the Observable.
	 */
	public void clearChanged() {
		obs.clearChanged();
	}
	
	/**
	 * Add an Observer to the Observable.
	 * @param observer The Observer.
	 */
	public void addObserver(final Observer observer) {
		obs.addObserver(observer);
	}
	
	/**
	 * Return the number of Observers registered with the Observable.
	 * @return An integer number of registered Observers.
	 */
	public int countObservers() {
		return obs.countObservers();
	}
	
	/**
	 * Remove the specified Observer from the list of registered Observers.
	 * @param o The Observer to remove.
	 */
	public void deleteObserver(final Observer o) {
		obs.deleteObserver(o);
	}
	
	/**
	 * Remove all Observers from the list of registered Observers.
	 */
	public void deleteObservers() {
		obs.deleteObservers();
	}
	
	/**
	 * Check the changed state of the Observable.
	 * @return True if changed.
	 */
	public boolean hasChanged() {
		return obs.hasChanged();
	}
	
	/**
	 * Notify all the registered Observers that there has been a change, 
	 * provided hasChanged() returns true.
	 */
	public void notifyObservers() {
		obs.notifyObservers();
	}
	
	/**
	 * Notify all the registered Observers that there has been a change,
	 * sending <code>arg</code> to their update() methods, provided hasChanged()
	 * returns true.
	 * @param arg The Object to send.
	 */
	public void notifyObservers(final Object arg) {
		obs.notifyObservers(arg);
	}

	/** {@inheritDoc} */
	@Override
	public void update(Observable o, Object arg) {
		// Override to utilize this method...
	}
}
